package org.NooLab.glue.msgframe;

import java.io.*;
import java.util.*;

import org.w3c.dom.*;

import org.NooLab.utilities.logging.PrintLog;


import javax.xml.transform.*;
import javax.xml.parsers.*;
import javax.xml.xpath.*;

import com.jamesmurty.utils.XMLBuilder;

 
import org.NooLab.utilities.xml.XMessageAbs;
import org.NooLab.utilities.xml.XMessageIntf;
import org.NooLab.utilities.xml.XpathQuery;

/*
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.util.JAXBResult;
import org.NooLab.utilities.files.DFutils;
import org.NooLab.utilities.strings.StringsUtil;
import org.NooLab.glue.components.pkg.TaskPackage;
*/
import org.NooLab.glue.net.RemoteAddress;
import org.NooLab.glue.transaction.*;




/*

	Driver employee   = read(Driver.class, "select * from drivers where id=1");
	Vehicle vehicle   = read(Vehicle.class, "select * from vehicles where id=1");

	returning instance of type defined by the class-literal

	public static <T> T read(Class<T> theClass, String sql)
		T o = theClass.newInstance();	
		return o;
	}
	
	needs a constructor
	
	public static void main(String[] args) throws Exception{
				        Class cl = Class.forName("Foo");
				        Object o = cl.getConstructor(Integer.TYPE, Integer.TYPE).newInstance(1,2);
				        Method m = cl.getMethod("add", Integer.TYPE, Integer.TYPE);
				       //  System.out.println(m.invoke(o, 5,10));
				    }
				    
see: http://tutorials.jenkov.com/java-reflection/dynamic-class-loading-reloading.html
     http://www.rgagnon.com/javadetails/java-0351.html

*/


/**
 * 
 * represents any kind of message to and from MessageBoard, 
 * thus provides methods to create and to parse XML into XMessage 
 * 
 * 
 * see: http://www.java-samples.com/showtutorial.php?tutorialid=152
 *      http://www.exampledepot.com/egs/org.w3c.dom/pkg.html
 *      
 *      XMLBuilder: http://code.google.com/p/java-xmlbuilder/wiki/ExampleUsage
 * 
 */
public class XMessage extends XMessageAbs implements XMessageIntf{

	// =================================

	// object references ..............
	XRequest xRequest;
	XRegistration xRegistration ; 
	
	
	
	// main variables / properties ....

	 
	// constants ......................
	
	

	// volatile variables .............

	
	
	// helper objects .................
	 


	// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
	public XMessage( PrintLog outprn ){
		super();
		
		out = outprn;
	}
	// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

	
	// ======================================================================================================

	public String createResultsNotificationMsg( String roleOfSender, String roleOfIssuer, String secret, 
												long notificationID,
												long transactID,
												long issuerInstanceId){
		
		String xmlstr = "";
		XMLBuilder builder ;

		try{

			builder = getXmlBuilder( "messageboard" ) ;
				
				builder.a( "name", "spela").a("role", roleOfSender); 
				 
				builder.e("transaction")
				         .e("transactionID").a("value", ""+transactID).up()
				         .e("issuer").a("role", ""+roleOfIssuer ).a("instanceID", ""+issuerInstanceId).up()
				         .e("notification").a("id", ""+notificationID).a("type", "results").a("secret", secret).up()
				         ;
				
				xmlstr = getXmlStr( builder, true ) ;
				
		}catch(Exception e){
		}
 
		return xmlstr;
		
	}
	
	/**
	 * 
	 * the "privatizationSecret" is needed to guarantee that the message is returned ONLY
	 * to the initiator of the calculation
	 * If it is empty in the original data delivery (by the SOURCE) of the transaction, it 
	 * COULD be (re-turn-)distributed to any other participant 
	 * 
	 * @param roleOfSender
	 * @param instanceID
	 * @param transactionID
	 * @param role
	 * @param privatizationSecret sth. like a GUID
	 * @param port
	 * @param host
	 * @return
	 */
	public String createNotificationReplyForResultCommand( // String roleOfSender, long instanceID , long transactionID, String role, String privatizationSecret,
										   			 	   BasicMessageParams basics,
										   			 	   String role, String requestCommand, // e.g. "get"
										   			 	   int port, String host ){
		String xmlstr = "";
		XMLBuilder builder ;
		
		try{

			builder = getXmlBuilder( "messageboard" ) ;
				
				builder.a( "name", "spela").a("role", role); 
				
				// port
				// str = xpathQuery.getAttributesValue( "//transaction/address/port", "port" , "value");
				// str = xpathQuery.getAttributesValue( "//transaction/address/host", "host" , "name");

				
				builder.e("transaction")
				         .e("transactionID").a("value", ""+basics.transactionID).up()
				         .e("instanceID").a("value", ""+basics.instanceID).up()
				         .e("role").a("value", basics.roleOfSender).up()
				         .e("notification").a("type", "results" ).a("request", requestCommand ).a("secret", basics.privateTransactionIdentifier).up()
				         .e("address").e("port").a("value", ""+port).up()                                      //  privatizationSecret
				         				.e("host").a("name", host).up().up()
				         ; 
				
				xmlstr = getXmlStr( builder, true ) ;
				
		}catch(Exception e){
		}

		
		return xmlstr;
	}
	
	
	// DataDeliveryParamsPlus
	// BasicMessageParams
	
	
	/*
	public String createDataDeliveryMessageFrame( String instanceName, String role, long transactID,
												  String privateTransactionIdentifier,
												  long ageOfExpiry,
												  String contentType, int dataType, boolean filterIncluded ,
												  int linkRelation, int relationItemID, int relationGroupID )
	*/
	public String createDataDeliveryMessageFrame( BasicMessageParams basics, DataDeliveryParamsPlus paramsplus){
	
		String xmlstr = "", filterInsertion = "";
		int taskRelayFlagValue , contextrequiredFlagValue=0;
		
		XMLBuilder builder ;
		
		/*
			<messageboard name="spela" role="SOURCE">
   				<transaction>
      				<id value="2"/>
      				<name value="test-source-1-85e949cc-de3d-48a7-996a-1475369e30e4"/>
      				<data type="">
      				</data>
   				</transaction>
			</messageboard>

		
		*/
		try{

		builder = getXmlBuilder( "messageboard" ) ;
			
			builder.a( "name", "spela").a("role", basics.roleOfSender); 
			
			if (paramsplus.filterIncluded){
				filterInsertion = "\n      <filter><!--##FILTER##--></filter>  \n";
			}
			if ( paramsplus.taskRelayFlag ){
				taskRelayFlagValue = 1;
			}else{
				taskRelayFlagValue = 0;
			}
			
			// should relaying be performed only if context matches ?
			if ( paramsplus.relayByContext ){
				contextrequiredFlagValue = 1;
			}else{
				contextrequiredFlagValue = 0;
			}

			
			// the "secret" will be saved together with the transactionID by the instance in a transparent manner, such that
			// even after restart of any of the components (or the connection) the results can be fetched !
			builder.e("transaction")
			         .e("transactionID").a("value", ""+ basics.transactionID).a("type", "relay").up()
			         .e("request").a("type", "delivery").a("secret", basics.privateTransactionIdentifier).up()
			         .e("name").a("value", basics.instanceName).up()
			         .e("content").a("type", paramsplus.contentType).up()	
			         .e("timedata").a("expiry", ""+paramsplus.ageOfExpiry).a("delivery", ""+System.currentTimeMillis()).up()
			         .e("linkrelation").a("value", ""+paramsplus.linkRelation).up()
			         .e("relationitemid").a("value", ""+paramsplus.relationItemID).up()
			         .e("relationgroupid").a("value", ""+paramsplus.relationGroupID).up()
			         .e("taskrelay")
			         		.a("value", ""+taskRelayFlagValue)
			         		.a("hopcount", ""+ paramsplus.relayHopsLimit )
			         		.a("contextrequired", ""+contextrequiredFlagValue).up()
			         .e("data").a("type", ""+paramsplus.dataType)
			         .c("##DATA##").up() 
			         ;
			 
			xmlstr = getXmlStr( builder, true ) ;
			
			xmlstr = xmlstr.replace("<data", filterInsertion+"<data");
		}catch(Exception e){
		}

		
		return xmlstr;
	}
	
	
	public String prepareDataDeliveryMessage( String inXmlMsg , Transaction transaction, String task ){
		/*
		
			<messageboard name="spela" role="SOURCE">
   				<transaction>
      				<transactionID value="13"/>
      				<request type="delivery"/>
      				<name value="test-source-1-7084ea07-3e98-4acd-ae1f-3a6d01de83f7"/>
      				<content type="rawdata,*"/>
      				<data type="9">
         				<format zip="0" encoding="base64"/>
         				<values>
							That's a real data table!
         				</values>
  
      				</data>
   				</transaction>
			</messageboard>

		*/
		String xmlstr="" ;
	 
		 
		  
		try{
			
			xpathQuery.setXml( inXmlMsg ) ;
		  
			// str =  xpathQuery.getXMLString();
			   
			xpathQuery.removeElement( "//transaction/name") ;
			xpathQuery.removeElement( "//transaction/request") ;
			
			xpathQuery.addChildTagElement("//transaction", "request");
			xpathQuery.addAttribute("//transaction/request", "task", task);
			
			xmlstr = xpathQuery.getXMLString() ;
			 
			
			// builder = getXmlBuilder( xmlstr ) ;
			// xmlstr = getXmlStr( builder, true ) ;
			
		}catch(Exception e){
			
		}
		
		
		return xmlstr;
	}

	public String createNotificationAboutRegistration( long instanceID, String role, int stateValue , String description){
		String xmlstr="" ;
		 
		int vi;
		XMLBuilder builder ;
		
		try{
              
			if ((stateValue>0) && (stateValue<90)){
				vi = 1;
			}else{
				vi = -1;
			}
			builder = getXmlBuilder( "messageboard" ).a( "name", "spela").a("role", role); 
			
			builder.e("register")
					.e("instance").a("id", ""+instanceID ).up()  
					.e("notification").a("type", "registration" ).up()
					.e("state").a("valid",""+vi)
								.a("value",""+stateValue)
								.a("description","description").up()
					.up()
					;
			
			xmlstr = getXmlStr( builder, true ) ;
			
		}catch(Exception e){
			
		}
		 
		return xmlstr;
		 
	}
	
	
	public String createConfirmationAboutDelivery( BasicMessageParams basics,// long transactionID, long instanceID, String role,  String deliveryID,
												   int stateValue,
												   String subject,    // e.g. "taskdata" or cancel:task 
												   String msgType){   // "n" -> notification, "c" -> confirmation
											 
						
		String xmlstr="" , ixs="";
		
		String   msgKind = "confirmation";
		 
		XMLBuilder builder,statevalTags=null ;
		
		msgType = msgType.toLowerCase() ;
		
		if ((msgType.length()==0) || 
			( (msgType.startsWith("n")==false) && (msgType.startsWith("c")==false) )){
			msgType = "c" ;
		}
		
		if (msgType.startsWith("n")){
			msgKind = "notification" ;
		}
		if (msgType.startsWith("c")){
			msgKind = "confirmation" ;
		}
		
		
		try{
            
			 
			builder = getXmlBuilder( "messageboard" ).a( "name", "spela").a("role", basics.roleOfSender); 
			
			if (stateValue>-999){
				statevalTags = getXmlBuilder( "state" ).a( "value",""+stateValue ).a("text", subject).up();
			}
			
			builder.e("transaction")
					.e("transaction").a("id", ""+basics.transactionID).up()
					.e(msgKind).a("type", subject ).a("secret", basics.privateTransactionIdentifier )
							.c("##SV##").up()
					.e("instance").a("id", ""+ basics.instanceID ).up()  
					
					;
			
			if (statevalTags!=null){
				ixs    = getXmlStr( statevalTags, false ) ;
			}
			xmlstr = getXmlStr( builder, true ) ;
			
			if (ixs.length()>2){
				xmlstr = xmlstr.replace("<!--##SV##-->", ixs);
			}else{
				xmlstr = xmlstr.replace("##SV##", " ");
			}
			
		}catch(Exception e){
			
		}
		
		
		return xmlstr;
	}
	
	/**
	 * message is sent by the SOURCE, which has received the results;
	 * the MessageBoard will keep any message as long
	 * @return 
	 */
	public String createConfirmationAboutReceivedResults( long transactionID, long instanceID, int transactionState, String secret, String role){
		
		String xmlstr="" ;
		 
		 
		XMLBuilder builder ;
		
		try{
            
			 
			builder = getXmlBuilder( "messageboard" ).a( "name", "spela").a("role", role); 
			
			builder.e("transaction")
					.e("transaction").a("id", ""+transactionID).a("state", ""+transactionState).up()
					.e("confirmation").a("type", "results" ).a("secret", secret).up()
					.e("instance").a("id", ""+instanceID ).up()  
					.e("role").a("value", ""+role).up()
					;
			
			xmlstr = getXmlStr( builder, true ) ;
			
		}catch(Exception e){
			
		}
		
		
		return xmlstr;
	}
	
	/**
	 * 
	 * this is used in cases where a dedicated advice has to be sent to the board
	 * 
	 * @return
	 */
	public String createTransactionAdviceBySource( long transactionID, long instanceID, 
												   String roleOfSender, String repliedSecret ,
												   String notificationContext , String action ) {
																					// e.g. drop
	  /*
	 	  <messageboard name="spela" role="BOARD">
		 	<transaction>
			 	<transactionID value="547"/>
			 	<issuer instanceID="2528" role="SOURCE"/>  // this needs a secret issued by the board !!!
			 	<notification type="results"/>
		 	</transaction>
		  </messageboard>
	  */
		
		String xmlstr = "";
		XMLBuilder builder ;

		try{

			builder = getXmlBuilder( "messageboard" ) ;
				
				builder.a( "name", "spela").a("role", roleOfSender); 
				
				builder.e("transaction")
				         .e("transactionID").a("value", ""+ transactionID).up()
				         .e("issuer").a("instanceID", ""+ instanceID).a("secret", repliedSecret).up()
				         .e("notification").a("type", notificationContext).up()
				         .e("action").a("value", action).up()
				       .up()  
				                                    // e.g. "results"
				         ;
				
				xmlstr = getXmlStr( builder, true ) ;
				
		}catch(Exception e){
		}

		return xmlstr;
		
		
	}
	
	
	/**
	 * 
	 * the same as the next one, for cases where there is transaction available
	 * 
	 * @param transactionID
	 * @param instanceID
	 * @param role
	 * @param privatizationSecret
	 * @return
	 */
	public String createReturnOfDataUponNotification( BasicMessageParams basics  ,  // long transactionID, long instanceID, String role, String privatizationSecret, 										  
													  int stateValue, int errCode, 
													  String description){

		String xmlstr="" ;
		 
		XMLBuilder builder ;

		try{
             
			 
			builder = getXmlBuilder( "messageboard" ).a( "name", "spela").a("role", "BOARD"); 
			
			builder.e("transaction")                            
					.e("transactionID").a("code",  ""+ errCode)
									   .a("secret", basics.privateTransactionIdentifier )
									   .a("state", ""+ stateValue)
									   .a("value", ""+ basics.transactionID)
					  .up()	   
					.e("instanceID").a("value", ""+basics.instanceID).up()
					.e("return").a("type", "results").a("to", basics.roleOfSender )
					.e("result").t( description ).up()
					;
			
			xmlstr = getXmlStr( builder, true ) ;
			
		}catch(Exception e){
			
		}
		
		
		return xmlstr;
		
	}
	/**
	 * message is sent by the MessageBoard, after notification / polling
	 * @param transaction
	 * @return
	 */
	public String createReturnOfDataUponNotification( Transaction transaction, String role, String privatizationSecret){
		
		String xmlstr="" ;
		 
		XMLBuilder builder ;

		try{
            /*
			  
	    	  
	    	  p1 = rawXmlStr.indexOf("<return ");
			p2 = rawXmlStr.indexOf("type=\"results\"");
			p3 = rawXmlStr.indexOf("<transactionID");

            */
		 
			builder = getXmlBuilder( "messageboard" ).a( "name", "spela").a("role", "BOARD"); 
			
			builder.e("transaction")                            
					.e("transactionID").a("value", ""+transaction.getTransactionID())
									   .a("state", ""+transaction.getTransactState())
									   .a("secret",privatizationSecret ).up()
					.e("instanceID").a("value", ""+transaction.getInstanceID()).up()
					.e("return").a("type", "results").a("to", role)
					.e("result").t(transaction.getResultObject()).up()
					;
			
			xmlstr = getXmlStr( builder, true ) ;
			
		}catch(Exception e){
			
		}
		
		
		return xmlstr;
	}


	public String createResourceForDataResultsUponRequest( Transaction transaction, String privatizationSecret){
		
		
		createReturnOfDataUponNotification( transaction, transaction.getRoleOfInitializer(), privatizationSecret) ;
		// encoded result object is as text in <result>...</result>
		
		
		return "";
	}

	public String createBoardShutdownMsg( XRegistration xreg, int restart  ){
		String xmlstr = "",  action="shutdown";
		XMLBuilder builder ;
		/*
		   <messageboard name="spela" role="BOARD">
				<system>
  				<shutdown/>
				</system>
		   </messageboard>
		 */
		try{

			builder = getXmlBuilder( "messageboard" ) ;
			
			builder.a( "name", "spela").a("role", "BOARD"); 
			
			
			if (restart==0){
				action = "shutdown";
			} else{
				if (restart>0){
					action = "restart";
				}
				if (restart<0){
					action = "disconnected"; // meaning, that the MessageBoard disappears
				}
			}
			
			builder.e("system").e(action)
									.a("id", ""+xreg.getInstanceID())
									.a("role", xreg.getRole())
									.a("name", xreg.getNameOfApplicant()) // this contains a GUID, which cannot be faked			
															   .up().up()
			;
			 
			xmlstr = getXmlStr( builder, true ) ;

		}catch(Exception e){
		}
		
		return xmlstr ;
	}
	/**
	 * 
	 * sent by the instance wishing to registrate
	 * Receptors must declare the type of content they are willing to accept !!
	 * sources must declare the type of content they are intending to send !!
	 * 
	 */
	public String createRegistration( BasicMessageParams basics , // String role , long instanceID, String name, 
									  int port, int listenport, 
									  double connectionDelay,
									  DataDeliveryParamsPlus paramsplus ){
									  // String contenttype, int linkRelation , int RelationItemID , int RelationGroupID){
	
		
		String xmlstr = "", vstr="", bv="",iidxmlstr="";
		XMLBuilder builder,registeredIID ;
		
		try{

			if (basics.instanceID>0){
				registeredIID = getXmlBuilder( "instance" ) ;
				registeredIID.a("id", ""+basics.instanceID).up() ;
			
				iidxmlstr = getXmlStr( registeredIID, false ).trim() ;
			}
			
			
			builder = getXmlBuilder( "messageboard" ) ;
			
			
			builder.a( "name", "spela").a("role", basics.roleOfSender); 
			
			vstr = Double.toString(connectionDelay); 
		 	if (paramsplus.uniqueInstance){
		 		bv = "1";
		 	}else{
		 		bv = "0" ;
		 	}
		 		
		 	
			builder.e("register")
			        .e("name").a("value", basics.instanceName).up()
			 		.e("instance").up()
			 		.e("port").a("value",""+port).up()
	                .e("listenport").a("value", ""+listenport).up()
	                .e("content").a("type", paramsplus.contentType).up()
	                .e("alignedResults").a("value", ""+paramsplus.alignedResults).up()
				  	.e("connectionDelay").a("value", ""+vstr).up()
				  	.e("timetolive").a("value", ""+paramsplus.timetolive).up()
				  	.e("unique").a("value", bv).up()
					.e("linkrelation").a("value", ""+paramsplus.linkRelation).up()
			     	.e("relationitemid").a("value", ""+paramsplus.relationItemID).up()
			     	.e("relationgroupid").a("value", ""+paramsplus.relationGroupID).up()
			     	.e("machine")
			     		.e("address").a("protocol", ""+paramsplus.protocolID).up()
			     		.e("address").a("list", paramsplus.ipAddressesStr).up().up()
			     	;
			 
			xmlstr = getXmlStr( builder, true ) ;

			if ((basics.instanceID>0) && (iidxmlstr.length()>0)){
				xmlstr = xmlstr.replace("<instance/>", iidxmlstr);
			}else{
				xmlstr = xmlstr.replace("<instance/>\n", "");
			}
		}catch(Exception e){
		}
		
		return xmlstr ;
	}
	
	public String createRegistrationDenialReply( BasicMessageParams basics, int reason, String description){
		
		String xmlstr = "", role=""  ;
		
		XMLBuilder builder ;
		
		try{

			 
			builder = getXmlBuilder( "messageboard" ) ;
			builder.a( "name", "spela").a("role", basics.roleOfSender); 
			
			builder.e("transaction")
			 		 .e("state").a("value", "denied")
			 		 			.a("code", ""+reason)
			 		 			.a("reason", description)
			 		 			.up()
			 		 .e("transaction").a("id", ""+basics.transactionID)
			 		                  .a("secret", basics.privateTransactionIdentifier).up()
			 		 .e("instanceID").a("value", ""+ basics.instanceID).up()
			 		 .e("name").a("value", basics.instanceName ).up()
			 ;
			
			xmlstr = getXmlStr( builder, true ) ;
			
		}catch(Exception e){
		}
		 
		
		return xmlstr ;
	}
	
	
	public String createRegistrationDenialReply( long instanceID, String name, String reason, String suggestion){
		 
		String xmlstr = "", role=""  ;
		
		XMLBuilder builder ;
		
		try{

			 
			builder = getXmlBuilder( "messageboard" ) ;
			builder.a( "name", "spela").a("role", "BOARD"); 
			
			
			
			builder.e("registration")
			 		 .e("state").a("value", "denied")
			 		 			.a("code", "-7")
			 		 			.a("reason", reason)
			 		 			.a("suggestion", suggestion)
			 		 			.up()
			 		 .e("instanceID").a("value", ""+instanceID).up()
			 		 .e("name").a("value", name).up()
			 ;
			
			xmlstr = getXmlStr( builder, true ) ;
			
		}catch(Exception e){
		}
		
		
		return xmlstr ;
		
		
	}
	
	/**
	 * returned by the MB following a registration request 
	 * 
	 */
	public String createRegistrationReply( XRegistration xRegistration, int sendModeOfBoard){
		 
		String xmlstr = "", role="", name=""  ;
		int port=0 , vports=0;
		long id = 0;
		
		XMLBuilder builder ;
		
		try{

			role = xRegistration.getRole() ;
			port = xRegistration.getPort() ;
			name = xRegistration.getNameOfApplicant() ;
			id   = xRegistration.getInstanceID() ;
			
			 
			builder = getXmlBuilder( "messageboard" ) ;
			builder.a( "name", "spela").a("role", role); 
			
			if (xRegistration.isVirtualPorts()){
				vports=1;
			}
			
			builder.e("registration")
			 		 .e("state").a("value", "completed").a("code", "0") .up()
			 		 .e("name").a("value", name).up()
	                 .e("id").a("value",""+ id ).up()
	                 
	                 .e("boardconfig")
	                 	.e("sending").a("mode", ""+sendModeOfBoard).up()
	                 	.e("activeport").a( "value", ""+xRegistration.getActiveport() )
	                      .e("virtualport").a("active",""+vports).a("value", ""+xRegistration.getMsgPortAllInOne() ).up()
	                    .up()  // </activeport>
	                 .up()
	                 
	                 .e("mboutport")
	                   // that's more or less just a confirmation, the value itself has been determined by the client itself
	                    .a("value", ""+xRegistration.getClientListeningPort() ).up()
	                 
	                 .e("linkrelation").a("value", ""+xRegistration.getSrlinkRelation()).up()
	                 .e("relationitemid").a("value", ""+xRegistration.getSrRelationItemID()).up()
					 .e("relationgroupid").a("value", ""+xRegistration.getSrRelationGroupID()).up()
					 .up();
			
			xmlstr = getXmlStr( builder, true ) ;

		}catch(Exception e){
		}
		
		
		return xmlstr ;
	}
	
	public String createUnRegistration(  long instanceId, String name, String role ) {
		String xmlstr = "";
		XMLBuilder builder ; 
		
		
		builder = getXmlBuilder( "messageboard" ) ;
		
		builder.a( "name", "spela").a("role", role);  ; 
		
		builder.e("register")
				.e("unregister")
	    		.e("name").a("value", name).up()
	    		.e("instance").a("id",""+instanceId).up().up().up()  
			    ;
		
		xmlstr = getXmlStr( builder, true ) ;
		
		return xmlstr ;
	}

	public String createConnectionConfirmMsg( long instanceID, String checkID, String role, String longname ){
		String xmlstr = "" ;
		XMLBuilder builder ;
		
		try{
			builder = getXmlBuilder( "messageboard" ) ;
			
			builder.a( "name", "spela").a("role", role); 
			
			builder.e("system")
			        .e("register") 
			        .e("check").a("type", "ping").a("id", checkID).up()
			        .e("instance").a("id", ""+instanceID).a("name", longname).up().up() ;
			 		 
			xmlstr = getXmlStr( builder, true ) ;

			
		}catch(Exception e){
		}
		
		return xmlstr ;
	}
	public String createConnectionCheckMsg( long instanceID, String checkID, String role, int mode ){
		
		String xmlstr = "" , requestmarker="",typeDetail="";
		XMLBuilder builder ;
		
		try{
			builder = getXmlBuilder( "messageboard" ) ;
			
			builder.a( "name", "spela").a("role", role); 
			
			if (mode<=0){
				requestmarker = "check" ;
				typeDetail = "ping" ;
			}
			if (mode>=1){
				requestmarker = "ping" ;
				typeDetail = "keepalive";
			}
			builder.e("system")
			        .e("register") 
			        .e(requestmarker).a("type", typeDetail).a("id", checkID).up()
			        .e("instance").a("id", ""+instanceID).up().up() ;
			 		 
			xmlstr = getXmlStr( builder, true ) ;

			
		}catch(Exception e){
		}
		
		return xmlstr ;
		
	}
	
	public String createStateUpdateNotificationForSource( long transactID, String privacyStr, int stateValue, String stateMsg, String role){
		String xmlstr = "" ;
		XMLBuilder builder ;
		
		try{
			builder = getXmlBuilder( "messageboard" ) ;
			
			builder.a( "name", "spela").a("role", role); 
			 
				builder.e("transaction")
				         .e("notification").a("type", "state").a("value", ""+stateValue ).a("description", stateMsg).up()
				         // .e("return").a("type", "state").a("to", role)
				         .e("transaction").a("id", ""+transactID).a("secret",privacyStr ).up()
				         ;

			;
			xmlstr = getXmlStr( builder, true ) ;

			
		}catch(Exception e){
		}
		
		return xmlstr ;
		
	}
	
	
	public boolean checkConnectionConfirmationMatch ( String rawXmlStr, long instanceID, String nameOfApplicant ){
		long iid;
		String name,cstr,str;
		boolean hb=false, iid_matches;
		
		
		// iid = getinstanceID( rawXmlStr, "instance") ;
		iid  = getSpecifiedValue(rawXmlStr, "instance", "id");
		name = getSpecifiedInfo(rawXmlStr, "instance", "name");
		
		if (instanceID>0){
			iid_matches = instanceID==iid;
		}else{
			iid_matches = true;
		}
		
		if ((nameOfApplicant.contentEquals(name)) && (iid_matches)){
			
			cstr = getNotificationInfo(rawXmlStr, "type");
			str  = getNotificationInfo(rawXmlStr, "value").trim();
			
			if ((str.contentEquals("1")) && (cstr.contentEquals("connection"))){
				hb = true ;
			}
		}
		return hb;
	}
	
	public String createNotificationAboutConfirmedConnection( long instanceID , String nameOfApplicant, String participantsRole, String issuerRole){
																				//  SOURCE/ RECEPTOR         "BOARD" 
		String xmlstr = "" ;
		XMLBuilder builder ;
		
		try{
			builder = getXmlBuilder( "messageboard" ) ;
			
			builder.a( "name", "spela").a("role", issuerRole); 
			 
				builder.e("transaction")
						.e("register").up()
				        .e("notification").a("type", "connection").a("value", "1").up()
				        .e("instance").a("id", ""+instanceID).a("name", nameOfApplicant) ;
			;
			xmlstr = getXmlStr( builder, true ) ;

			
		}catch(Exception e){
		}
		
		return xmlstr ;
	}
	
	public String createCancellationConfirmation( BasicMessageParams basics, String subject, String listedIDs, String  notTreatedRqTids ){

		String xmlstr = "" ;
		XMLBuilder builder ;
		
		try{
			builder = getXmlBuilder( "messageboard" ) ;
			
			builder.a( "name", "spela").a("role", basics.roleOfSender ); 
			 
			 
			builder.e("transaction")
					.e("transaction").a("id", ""+basics.transactionID).a("secret", basics.privateTransactionIdentifier ).up()
					.e("control").a("type", subject ).up()
					.e("confirmation").a("success", listedIDs).a("unknown", notTreatedRqTids)	.up() 
					.e("instance").a("id", ""+ basics.instanceID ).up()  
					
					;
			;
			xmlstr = getXmlStr( builder, true ) ;

			
		}catch(Exception e){
		}
		
		return xmlstr ;
	}
	
	public String createCancelAllTaskMessage( String fullname, long instanceID , 
			 								  String privateTransactionIdentifier, String role , String parameters ){
		
		String xmlstr = "" ;
		XMLBuilder builder ;
		
		try{
			builder = getXmlBuilder( "messageboard" ) ;
			
			builder.a( "name", "spela").a("role", role); 
			 
				builder.e("transaction")
				        .e("control").a("secret", privateTransactionIdentifier).up()
				        .e("transaction").a("id", "-9").up()
				        .e("instance")
				        	 .a("id", ""+instanceID)
				        	 .a("name", fullname)
				        	 .up()
						.e("task").a("type", "cancel").a("param", parameters).up()
						 
			;
			xmlstr = getXmlStr( builder, true ) ;

		
		}catch(Exception e){
		}
		
		return xmlstr ;
	}
	
	public String createControlTaskMessage( long transactionID, String taskname, String parameters,
										    String privateTransactionIdentifier,
											long instanceID , String role  ){
		
		
		String xmlstr = "" ;
		XMLBuilder builder ;
		
		try{
			builder = getXmlBuilder( "messageboard" ) ;
			
			builder.a( "name", "spela").a("role", role); 
			 
				builder.e("transaction")
				        .e("control").a("secret", privateTransactionIdentifier).up() 
				        .e("transaction").a("id", ""+transactionID).up()
				        .e("instance").a("id", ""+instanceID).up()
						.e("task").a("type", "cancel").a("param", parameters).up()
						 
			;
			xmlstr = getXmlStr( builder, true ) ;

		
		}catch(Exception e){
		}
		
		return xmlstr ;
	}
	
	
	
	
	public String readRegistrationsConnectionCheck( String rawXmlMsg ){
		
		String str="", checkGUID ;
		long iid;
		
		try{
			 // <iid>::<GUID>
			 
			xpathQuery.setXml( rawXmlMsg ) ;

			str = xpathQuery.getAttributesValue( "//messageboard" , "messageboard", "name");
			
			checkGUID = xpathQuery.getAttributesValue( "//register/check", "check", "id");
			
			str = xpathQuery.getAttributesValue( "//register/instance", "instance", "id");
				  iid = getLong(str, -1) ;
			
			str = ""+iid+"::"+checkGUID;
			
			
		}catch(Exception e){
			e.printStackTrace();
		}
		
		return str ;
	}


	public XRegistration readUnRegistration( String rawXmlMsg ){
		/*
		  		
				<messageboard name="spela" role="RECEPTOR">
				   <register>
				      <unregister>
				      	<name value="testReceptor0-receptor-1-4781aac9-ce2d-4575-9ace-7daedda073ba"/>
				      	<instance id="2838"/>
				      </unregister>
				   </register>
				<originator id="BaseResource$MessageSupply@cd927d"/>
				</messageboard>
		  
		 */
		String str, vstr,pstr, mbdetails;
		int portval=0;
		long regID = 0;
		
		
		XRegistration xRegistration=null ;
		

		try{

			xRegistration = new XRegistration();
			xRegistration.setOutPrn(out);
			
			xpathQuery.setXml( rawXmlMsg ) ;

			mbdetails = xpathQuery.getAttributesValue( "//messageboard" , "messageboard", "name");

			if (mbdetails.contains("spela")==false){
				return null ;
			}
			mbdetails = xpathQuery.getAttributesValue( "//messageboard" , "messageboard", "role");

			xRegistration.setRole(mbdetails) ;
			
			str = xpathQuery.getAttributesValue( "//unregister/name" , "name", "value");
			 
			// the port the MessageBoard uses for listening (and the client for sending to)
			vstr = xpathQuery.getAttributesValue( "//unregister/instance" , "instance", "id");

			// the port the client is using to listen for messages sent by the MessageBoard
			// the MessageBoard uses a dedicated port for any of the clients,
			// broadcasting is done via the service port ?? 
			pstr = xpathQuery.getAttributesValue( "//unregister/listenport" , "listenport", "value");
			
			xRegistration.setNameOfApplicant(str) ;

			
			if ((vstr.length()>0) && (strgutil.isNumericX(vstr))){
				regID = Long.parseLong(vstr) ;
			}
			
			xRegistration.setInstanceID(regID) ;
			
			portval = -1;
			if ((pstr.length()>0) && (strgutil.isNumericX(pstr))){
				portval = Integer.parseInt(pstr) ;
			}
			xRegistration.setClientListeningPort(portval) ;
			
			
		}catch(Exception e){
			e.printStackTrace();
		}
		
		
		
		
		return xRegistration;
	}
	
	
	/**
	 * 
	 * reading the registration by the MessageBoard
	 */
	public XRegistration readRegistrationRequest( String rawXmlMsg ){

		String str, vstr,pstr, mbdetails;
		int portval=0, vi;
		double vd;
		long iid, vv;
		
		XRegistration xRegistration=null ;
		
		try{

			xRegistration = new XRegistration();
			xRegistration.setOutPrn(out);
			
			xRegistration.setInstanceID(-1) ;
			
			xpathQuery.setXml( rawXmlMsg ) ;

			mbdetails = xpathQuery.getAttributesValue( "//messageboard" , "messageboard", "name"); 

			if (mbdetails.contains("spela")==false){
				return null ;
			}
			mbdetails = xpathQuery.getAttributesValue( "//messageboard" , "messageboard", "role");

			xRegistration.setRole(mbdetails) ;
			
			// this is only available if 
			str = xpathQuery.getAttributesValue( "//register//instance" , "instance", "id");
			      if (str.length()>0){
			    	  iid = getLong(str,-1);
			    	  if (iid>0){
			    		  xRegistration.setInstanceID( iid ) ;
			    	  }
			      }
			vi=0;      
			str = xpathQuery.getAttributesValue( "//register/unique" , "unique", "value");
				  if (str.length()>0){
					  vi = Integer.parseInt(str) ;
				  }
				  boolean hb = vi>=1;
				  xRegistration.setInstanceIsUnique(hb);
				  
				  
			str = xpathQuery.getAttributesValue( "//register//name" , "name", "value");
			 
			// the port the MessageBoard uses for listening (and the client for sending to)
			vstr = xpathQuery.getAttributesValue( "//register//port" , "port", "value");
				   if ((vstr.length()>0) && (strgutil.isNumericX(vstr))){
					   portval = Integer.parseInt(vstr) ;
				   }
			// the port the client is using to listen for messages sent by the MessageBoard
			// the MessageBoard uses a dedicated port for any of the clients,
			// broadcasting is done via the service port ?? 

			pstr = xpathQuery.getAttributesValue( "//register//listenport" , "listenport", "value");
				   xRegistration.setNameOfApplicant(str) ;

			str = xpathQuery.getAttributesValue( "//register//content" , "content", "type");
				  xRegistration.setAcceptType(str) ;
			
			str = xpathQuery.getAttributesValue( "//register//alignedResults" , "alignedResults", "value");
				  vi = getInteger( str, -1);
				  xRegistration.setAlignedResultsBasketSize(vi) ;
				   
			
			xRegistration.setPort(portval) ;
			
			portval = getInteger( pstr, -1);

			xRegistration.setClientListeningPort(portval) ;
			
			str = xpathQuery.getAttributesValue( "//register//connectionDelay" , "connectionDelay", "value");
				  vd = getDouble( str, 2.0);
				  xRegistration.connectionDelay = vd;
				  
			str = xpathQuery.getAttributesValue( "//register//linkrelation" , "linkrelation", "value");
				  vi = getInteger( str, -1);
				  xRegistration.setSrlinkRelation(vi) ;
			str = xpathQuery.getAttributesValue( "//register//relationitemid" , "relationitemid", "value");
				  vi = getInteger( str, -1);
				  xRegistration.setSrRelationItemID(vi);
			str = xpathQuery.getAttributesValue( "//register//relationgroupid" , "relationgroupid", "value");
				  vi = getInteger( str, -1);
				  xRegistration.setSrRelationGroupID(vi);
	 
			// ---------------------------------------
			str = xpathQuery.getAttributesValue( "//register//timetolive" , "timetolive", "value");
				  vv = getLong( str, -1);
				  xRegistration.setTimetolive(vv) ;
				  
			str = xpathQuery.getAttributesValue( "//register/machine/address" , "address", "protocol");
				  vi = getInteger( str, -1);
				  xRegistration.setProtocolID(vi) ;
				  
				  
		}catch(Exception e){
			e.printStackTrace();
		}
		
		 
		return xRegistration ;
	}
	
	/**
	 * 
	 * reading the registration by the registrant
	 */
	public XRegistration readConfirmedRegistration( String rawxmlStr ){
		/*
			<messageboard name="spela" role="SOURCE">
   				<registration>
     				<state code="0" value="completed"/>
      				<name value="testsource0-source-1-7132c490-f138-11e0-84ce-e0f847024516"/>
      				<id value="1867"/>
      				<boardconfig>
         				<sending mode="3"/>
         				<activeport value="7100">
            				<virtualport active="0" value="-1"/>
         				</activeport>
      				</boardconfig>
   				</registration>
   				<mboutport value="7001"/>
   				<linkrelation value="2"/>
   				<relationitemid value="-1"/>
   				<relationgroupid value="-1"/>
			</messageboard>

		*/
	
		long instanceID ;
		int portnumber,vi ;
		 
		String str, mbdetails ;
		XRegistration xRegistration = new XRegistration() ;
		xRegistration.setOutPrn(out);
		
		xpathQuery.setXml( rawxmlStr ) ;

		mbdetails = xpathQuery.getAttributesValue( "//messageboard" , "messageboard", "name");

		if (mbdetails.contains("spela")==false){
			return null ;
		}

		mbdetails = xpathQuery.getAttributesValue( "//messageboard" , "messageboard", "role");
		xRegistration.setRole(mbdetails) ;
		
		str = xpathQuery.getAttributesValue( "//registration//name" , "name", "value");
			  xRegistration.setNameOfApplicant(str) ;
		// <name value="testReceptor-receptor-1-10f600e0-3305-4f74-a86c-f0b23fee4b10"/>
		
		str = xpathQuery.getAttributesValue( "//registration//boardconfig/activeport" , "activeport", "value");
			  portnumber = getInteger(str,-1) ;
			  xRegistration.setActiveport(portnumber) ;
			  xRegistration.setPort(portnumber) ;
		
		str = xpathQuery.getAttributesValue( "//registration//boardconfig/sending" , "sending", "mode");
			  vi = getInteger(str, 0) ;
			  // this attribute expresses the board's "boardSendMode", if =0, then the board is passive
			  xRegistration.setBoardSendMode(vi);
		
		
		str = xpathQuery.getAttributesValue( "//registration//mboutport" , "mboutport", "value");
			  portnumber = getInteger(str,-1) ;
			  xRegistration.setClientListeningPort(portnumber) ;

		str = xpathQuery.getAttributesValue( "//registration//linkrelation" , "linkrelation", "value");
		      vi = getInteger(str,-1);
		      xRegistration.setSrlinkRelation(vi);
		str = xpathQuery.getAttributesValue( "//registration//relationitemid" , "relationitemid", "value");
			  vi = getInteger(str,-1);
			  xRegistration.setSrRelationItemID(vi);
		str = xpathQuery.getAttributesValue( "//registration//relationgroupid" , "relationgroupid", "value");
		      vi = getInteger(str,-1);
		      xRegistration.setSrRelationGroupID(vi) ;
		      
		str = xpathQuery.getAttributesValue( "//registration//id" , "id", "value");
			  instanceID = Long.parseLong(str) ;
			  instanceID = getLong( str, -1);
			  xRegistration.setInstanceID(instanceID) ;
		    
		 /*   
			.e("boardconfig")
         	.e("sending").a("mode", boardSendMode).up()
         	.e("activeport").a( "value", ""+xRegistration.getActiveport() )
              .e("virtualport").a("active",""+vports).a("value", ""+xRegistration.getMsgPortAllInOne() ).up()
              .up()  // </activeport>
            .up()
         .up()
		   */
		      
		return xRegistration;
	}
	
	public long getTransactionID( String rawXmlMsg ){
		/*
			<messageboard name="spela" role="RECEPTOR">
				<transaction>
					<transactionID value="142"/>
				.......   ........ 
		*/
		long transactID=-1;
		
		String str ;
		
		xpathQuery.setXml( rawXmlMsg ) ;

		str = xpathQuery.getAttributesValue( "//transaction/transactionID" , "transactionID", "value");
		if (str.length()==0){
			str = xpathQuery.getAttributesValue( "//transaction/transactionid" , "transactionid", "value");	
		}
		if (str.length()==0){
			str = xpathQuery.getAttributesValue( "//transaction/transaction" , "transaction", "id");	
		}
		transactID = getLong(str, -1) ;
		
		return transactID;
	}
	
	public long getinstanceID( String rawXmlMsg, String domainSpecs) { // "issuer") 
		long instanceID = -1;
		
		String str ;
		try{
		xpathQuery.setXml( rawXmlMsg ) ;
		   
		 
		
		// by default: transaction, sometime also : control
		// str = xpathQuery.getAttributesValue( "//"+contentRoot+"/"+domainSpecs , domainSpecs, "value");
		str = xpathQuery.getAttributesValue( "/*/"+domainSpecs , domainSpecs, "value");
		if (str.length()==0){
			str = xpathQuery.getAttributesValue( "//"+contentRoot+"/"+domainSpecs , domainSpecs, "value");
		}
		
		if (str.length()==0){
			//str = xpathQuery.getAttributesValue( "//"+contentRoot+"/"+domainSpecs , domainSpecs, "id");
			str = xpathQuery.getAttributesValue( "/*/"+domainSpecs , domainSpecs, "id");
		}
		if (str.length()==0){
			// str = xpathQuery.getAttributesValue( "//"+contentRoot+"/"+domainSpecs+"id" , domainSpecs+"id", "value");
			str = xpathQuery.getAttributesValue( "/*/"+domainSpecs+"id" , domainSpecs+"id", "value");
		}
		instanceID = getLong(str, -1) ;
		}catch(Exception ex){}
		return instanceID;
	}
	
	public int getinstanceIDfromIssuer( String rawXmlMsg ) { // "issuer") 
		int instanceID = -1;
		
		String str ;
		
		xpathQuery.setXml( rawXmlMsg ) ;
		
		str = xpathQuery.getAttributesValue( "//transaction/issuer" , "issuer", "instanceID");
		instanceID = getInteger(str, -1) ;

		
		return instanceID;
	}
	
	   /*
	  <transaction>
	      <transactionID value="259"/>
	      <issuer instanceID="1569" role="SOURCE"/>
	      <notification type="results"/>
	  </transaction>

       */
    public String getNotificationInfo(String rawXmlMsg, String attrSpecs) { // "type") ;
    	String infoStr="";
    	 
		xpathQuery.setXml( rawXmlMsg ) ;
		
		infoStr = xpathQuery.getAttributesValue( "//transaction/notification" , "notification", attrSpecs );
		 
    	return infoStr;
    }
 
    
    public int getNotificationStateValue(String rawXmlMsg, String attrSpecs, int defaultValue) { // "value") ;
    	
    	String infoStr="";
    	int result= defaultValue;
		 
		
		xpathQuery.setXml( rawXmlMsg ) ;
		
		infoStr = xpathQuery.getAttributesValue( "//transaction/notification" , "notification", attrSpecs );
				  result = getInteger( infoStr, defaultValue);
		
    	return result;
    }
    
    /**
	 * the instance of role SOURCE is requesting the states available for its Receipt ID from the MessageBoards
	 */
	public Object getAvailableStateMsg(  String rawXmlMsg, String xpathStr, String domainSpecs, String attrSpecs, int v){ 
										// "/state/item", "description","value"  ,0){
		/*
		 *  <transaction>
	  			<transactionID value="524"/>
	  			<instance id="2578"/>
	  			<return type="state"/>
	  			<state>
	     			<item description="" value="20"/>
	  			</state>
				</transaction>
		 */
		
    	String infoStr="";
    	int result = -1; 
    	int defaultValue = -1;
	 
		xpathQuery.setXml( rawXmlMsg ) ;
		
		infoStr = xpathQuery.getAttributesValue( "//transaction"+xpathStr , domainSpecs, attrSpecs );
				  result = getInteger( infoStr, defaultValue);
		
    	return (Object)result;
	}
	
	
	public long getTimeDataValue( String rawXmlMsg, String attrSpecs, long defaultValue){
    	long result = defaultValue;
    	String str;
    	
    	xpathQuery.setXml( rawXmlMsg ) ;
    	
    	str = xpathQuery.getAttributesValue( "//timedata" , "timedata", attrSpecs );
    		  result = getLong(str, defaultValue) ;
    		  
    	return result;
    }
    
    public RemoteAddress getRemoteAddress( String rawXmlMsg, String additionalPath){
    	RemoteAddress addr = new RemoteAddress();
    	
		String str ;
		int port=0;
		xpathQuery.setXml( rawXmlMsg ) ;
		
		str = xpathQuery.getAttributesValue( "//transaction/"+additionalPath+"address/port", "port" , "value");
			  port = getInteger(str,0);
		str = xpathQuery.getAttributesValue( "//transaction/"+additionalPath+"address/host", "host" , "name");

		addr.setPort(port);
		addr.setHostname(str) ;
		
    	return addr;
    }
    
    /**
     * 
     * @param rawXmlMsg
     * @param xmlpath  sth like "//transaction/return/result", where the last step then would be &lt;result&gt;text&lt;/result&gt; 
     * @return
     */
    public String getIncludedXText( String rawXmlMsg , String xmlpath){
    	String xtext="" ;
    	
    	xpathQuery.setXml( rawXmlMsg ) ;
    	
    	xtext = xpathQuery.getElementsIncValue( xmlpath  ).trim();
    	
    	return xtext;
    }
    
    /**
     * 
     * used by SOURCEs
     * 
     * @param rawXmlMsg
     * @return
     */
    public String readReturnedResults( String rawXmlMsg ){
    	String encodedObj="" ;
    	
    	xpathQuery.setXml( rawXmlMsg ) ;
    	
    	encodedObj = xpathQuery.getElementsIncValue( "//transaction/return/result" ).trim();
    	encodedObj = strgutil.trimm(encodedObj, "/n") ;
		
    	return encodedObj;
    }
	/**
	 * 
	 * used by MessageBoard to read a message, which contains a returned result
	 * 
	 * @param rawXmlMsg
	 * @return
	 */
	public Transaction readReturnedResults( Transactions transactions,boolean acceptUnknownTransactions, String rawXmlMsg ){
		
		/*
			<messageboard name="spela" role="RECEPTOR">
				<transaction>
  				<transactionID value="142"/>
  				<request type="return"/>
  				<data> 
     				... encoded data
  				</data>
				</transaction>
			</messageboard>

	
		 */
		 
		long transactionID ;
		String str;
		
		Transaction transaction = null;
		
		 	
		xpathQuery.setXml( rawXmlMsg ) ;
		 	
		transactionID =  getTransactionID(rawXmlMsg) ;
		
		if (transactionID>0){
			transaction = transactions.getTransactionByID( transactionID ) ;
			
			if ((transaction!=null) || (acceptUnknownTransactions)){
				str = xpathQuery.getElementsIncValue("//transaction/data").trim();
				str = strgutil.trimm(str, "/n");
				transaction.setResultObject(str);
			}
			// it is still encoded ! 
		}else{
			
		}
		
		return transaction;
	}
	
	/**
	 * 
	 * used by receptor to get the message
	 * 
	 * @param rawXmlMsg
	 * @return
	 */
	public Transaction readReceptorTransaction( String rawXmlMsg ) {
		/*
			<messageboard name="spela" role="SOURCE">
			 	<transaction>
     				<transactionID value="45"/>
      				<content type="rawdata"/>
      				<data type="9">
         				<format encoding="base64" zip="0"/>
         				<values>
							That's a real data table!
         				</values>
  
			  		</data>
   					<request task=""/>
				</transaction>
		 	</messageboard>
		
		*/
		 
		String str ;
		int   dtype=0 ;
		long  idval=-1 ;
		
		Transaction transaction;
		
		transaction = readConfirmedTransactionReceipt( rawXmlMsg );
		
		// additional stuff like data type, format, task, task parameter (itself a XML [from object])
		
		xpathQuery.setXml( rawXmlMsg ) ;

		str = xpathQuery.getAttributesValue( "//transaction/transactionID" , "transactionID", "value");
		idval = strgutil.getNumFromStr(str,0) ;
		transaction.setTransactionID(idval);
		

		str = xpathQuery.getAttributesValue( "//transaction/data" , "data", "type");
		dtype = strgutil.getNumFromStr(str,0) ;
		transaction.setType(dtype) ;


		str = xpathQuery.getAttributesValue( "//transaction/content" , "content", "type");
		transaction.setContentType( str ) ;

		
		str = xpathQuery.getAttributesValue( "//transaction/data/format" , "format", "encoding");
		transaction.setDataEncoding( str ) ;
		
		
		str = xpathQuery.getAttributesValue( "//transaction/data/format" , "format", "zip");
		transaction.setDataCompression( strgutil.getNumFromStr(str,0)  ) ;
		
		
		str = xpathQuery.getElementsIncValue( "//transaction/data/values" ).trim();
		str = strgutil.trimm(str, "/n") ;
		transaction.setDataObject( str ) ;
		
		str = xpathQuery.getAttributesValue( "//transaction/request" , "request", "task");
		// transaction.  ) ;
		
		//this is most likely also a xml, which we need as xml!!!
		str = xpathQuery.getElementsIncValue( "//transaction/request/parameters" );
		
		return transaction;
	}
	
	public Transaction readConfirmedTransactionReceipt( String rawXmlMsg ) {
		
		/*
		
			<messageboard name="spela" role="SOURCE">
   				<transaction>
   				  	<id instance="273" value="4"/>
      				<name value="test-source-1-1e61ac60-acea-4b4c-87ea-8f00406cb30c"/>
   				</transaction>
			</messageboard>
		*/
		
		String str ;
		 
		long val=-1, idval=-1 ;
		Transaction transaction;
		
		transaction = new Transaction();
		
		try{
			
			xpathQuery.setXml( rawXmlMsg ) ;
			
			str = xpathQuery.getAttributesValue( "//messageboard" , "messageboard", "role");
			transaction.setRoleOfInitializer(str) ;
			
			str = xpathQuery.getAttributesValue( "//transaction//id" , "id", "instance");
			
			if ((str.length()>0) && (strgutil.isNumericX(str))){
				idval = Long.parseLong(str);
				transaction.setInstanceID(idval);
			}

			str = xpathQuery.getAttributesValue( "//transaction//id" , "id", "value");
			if ((str.length()>0) && (strgutil.isNumericX(str))){
				val = Long.parseLong(str);
				transaction.setTransactionID(val) ;
			}
			
			str = xpathQuery.getAttributesValue( "//transaction//name" , "name", "value");
			transaction.setNameOfInitializer(str) ;
			
		}catch(Exception e){
			// TODO : create a log entry ... for all such cases
			 
		}
		 
		return transaction ;
	}

	public Transaction readRequestForTransactionReceipt( String rawXmlMsg ) {
		Transaction transaction;
		/*
			<messageboard name="spela" role="SOURCE">
   				<request type="transaction">
      				<role value="SOURCE"/>
      				<instance id="255"/>
   				</request>
			</messageboard>

		
		*/

		String str ;
		 
		long val ;
		
		transaction = new Transaction () ; 
		
		try{
			
			xpathQuery.setXml( rawXmlMsg ) ;
			str = xpathQuery.getAttributesValue( "//messageboard//request" , "request", "type");
			
			if (str.contentEquals("transaction")){
			
				str = xpathQuery.getAttributesValue( "//request//role" , "role", "value");
				transaction.setStarterRole(str) ;
			
				str = xpathQuery.getAttributesValue( "//request//instance" , "instance", "id");
				
				if (str.length()>0){
					
					if (strgutil.isNumericX(str)){
						val = Long.parseLong(str) ;
						if (val>0){
							transaction.setInstanceID(val) ;
						}
					} // is num ?
				} // str > ""
			
			} // contains "transaction" ?
			
		}catch(Exception e){
			
		}
		
		
		return transaction ; 
	}
	
	
	// ------------------------------------------
	// ------------------------------------------

	/**
	 * the receptors return state messages to the MessageBoard, which assigns it to the respective Receipt ID,
	 * later, the instance of role SOURCE then may request this state from the MessageBoard
	 * 
	 * the ReceptorStateMsg may contain data (must be indicated)
	 * 
	 */
	public String createReceptorStateMsg( long instanceID , String role, long transactID , int stateValue, String description){
		
		String xmlstr="" ;


		XMLBuilder builder ;
		
		try{
  
			builder = getXmlBuilder( "messageboard" ) ;
			builder.a( "name", "spela").a("role", role); 

			builder.e("transaction")
	         		.e("transactionID").a("value", ""+transactID).up() // should NOT contain uppercase chars!!!!
	         		.e("instance").a("id", ""+instanceID).up()
	         		.e("return").a("type", "state").up()
	         
	         		.e("state")
	         		.e("item") 
	         				  .a("value", ""+stateValue)
	         				  .a("description", description).up(); // there could be several
	        
			
			xmlstr = getXmlStr( builder, true ) ;
			

		}catch(Exception e){
		}
		
		
		 
		return xmlstr;
		

			
	}
	public String createReceptorResultReturnMsg( long instanceID, long transactID , String role, int port){
		String xmlstr="" ;


		XMLBuilder builder ;
		
		try{
  
			builder = getXmlBuilder( "messageboard" ) ;
			builder.a( "name", "spela").a("role", role); 
			
			 
			builder.e("transaction")
			         .e("transactionID").a("value", ""+transactID).up()
			         .e("instance").a("id", ""+instanceID).a("port", ""+port).up()
			         .e("request").a("type", "return").up()
			         
			         .e("data")
			         .c("##DATA##").up() 
			         ;

			
			xmlstr = getXmlStr( builder, true ) ;
			

		}catch(Exception e){
		}
		
		
		 
		return xmlstr;
		
	}
	
	/*
	    if the task of the receptor is expected to create a result (must be indicated by the SOURCE):
		on completion of the task the receptor sends a state message for completion to the board,
		along with the results in the data section (Base64 encoded objects)
		
	*/
	
	// ------------------------------------------
	// ------------------------------------------
	
	public String createRequestForResultStateResource( long transactionID,
													   long instanceID,
													   String clientSecret, 
													   String role){
		String xmlstr="" ;
		
		
		XMLBuilder builder ;
		
		try{
	
			
			builder = getXmlBuilder( "messageboard" ) ;
			builder.a( "name", "spela").a("role", role); 
			
			
			builder.e("transaction")
			         .e("request").a("type", "return").a("content","resource;state;").a("secret", clientSecret).up()
                     .e("transaction").a("id",""+ transactionID ).up()  
                     .e("instanceID").a("value", ""+instanceID).up()
			         .e("role").a("value", role).up()
	               .up();
					 
	                 
			xmlstr = getXmlStr( builder, true ) ;
	
		}catch(Exception e){
		}
		
		
		 
		return xmlstr;
		
	}
	
	public String createRequestForRetrieveBulk( long instanceID, String fullname , String contentType){
		
		String xmlstr="",excluded="" ;
		
		XMLBuilder builder ;
		
		try{
	
			
			builder = getXmlBuilder( "messageboard" ) ;
			builder.a( "name", "spela").a("role", "SOURCE"); 
			
			builder.e("transaction")
			         .e("request").a("type", "task").a("content","resource").up()
                     .e("instanceID").a("value", ""+instanceID).up()
                     .e("content").a("type", contentType).up()
                     .e("excluded").a("values", ""+excluded).up()
	               .up();
	                 
			xmlstr = getXmlStr( builder, true ) ;
	
		}catch(Exception e){
		}
		 
		return xmlstr;
	}
	
	
	public String createRequestForTaskResource( long instanceID, Vector<Long> excludedTransactionIDs, String role, String contentType ){
		
		String xmlstr="",excluded="" ;
		
		XMLBuilder builder ;
		
		try{
	
			excluded = strgutil.arr2text(excludedTransactionIDs, ";");
			
			
			builder = getXmlBuilder( "messageboard" ) ;
			builder.a( "name", "spela").a("role", role); 
			
			builder.e("transaction")
			         .e("request").a("type", "task").a("content","resource").up()
                     .e("instanceID").a("value", ""+instanceID).up()
                     .e("content").a("type", contentType).up()
                     .e("excluded").a("values", ""+excluded).up()
                     
			         .e("role").a("value", role).up()
	               .up();
					 
	                 
			xmlstr = getXmlStr( builder, true ) ;
	
		}catch(Exception e){
		}
		
		
		 
		return xmlstr;
	}

	
	public String createDownloadRequestForTaskResource( long transactionID, long instanceID, String resourceKeyStr, String role){

		String xmlstr="" ;
		
		XMLBuilder builder ;
		
		try{
			
			builder = getXmlBuilder( "messageboard" ) ;
			builder.a( "name", "spela").a("role", role); 
			
			builder.e("transaction") 	
			         .e("request").a("type", "task").a("content","resource").up()
			         .e("transaction").a("id", ""+transactionID).up()
                     .e("instanceID").a("value", ""+instanceID).up()
			         .e("resource").a("value", resourceKeyStr) 
	               .up();
			          
	                 
			xmlstr = getXmlStr( builder, true ) ;
	
					// next step will include then the data
					// 	.e("result").t(transaction.getResultObject()).up()
					// and the content will be data:  "content","data", besides the fact that their will be a section <data>
		}catch(Exception e){
		}
		 
		return xmlstr;
		
		
	}
	
	
	public String createNoResourceMsgForReceptor( long instanceID, String role, String str){
		String xmlstr="" ;
		
		XMLBuilder builder ;
		
		try{
			
			builder = getXmlBuilder( "messageboard" ) ;
			builder.a( "name", "spela").a("role", role); 
			
			
			// ("request").a("type", "transaction")
	           
			builder.e("response") // response is ONLY for asynchronous (httpc-like) transports
								  // indicating a within session notification / return, 
								  // for cases where we do not have a transaction ID available	
			         .e("return").a("type", "task").a("content","resource").up()
			         .e("transactionID").a("value", "-1").up()
                     .e("instanceID").a("value", ""+instanceID).up()
			         .e("resource").a("value", "noresource").up() 
	               .up();
			          
	                 
			xmlstr = getXmlStr( builder, true ) ;
	
					// next step will include then the data
					// 	.e("result").t(transaction.getResultObject()).up()
					// and the content will be data:  "content","data", besides the fact that their will be a section <data>
		}catch(Exception e){
		}
		 
		return xmlstr;
	}
	public String createResourceMappingUponTaskRequest( long transactionID, long instanceID, String role, String guidStr ){
		
		String xmlstr="" ;
		
		XMLBuilder builder ;
		
		try{
			
			builder = getXmlBuilder( "messageboard" ) ;
			builder.a( "name", "spela").a("role", role); 
			
			
			// ("request").a("type", "transaction")
	           
			builder.e("response") // response is ONLY for asynchronous (httpc-like) transports
								  
			         .e("return").a("type", "task").a("content","resource").up()
			         .e("transactionID").a("value", ""+transactionID).up()
                     .e("instanceID").a("value", ""+instanceID).up()
			         .e("resource").a("value", guidStr) 
	               .up();
			          
	                 
			xmlstr = getXmlStr( builder, true ) ;
	
					// next step will include then the data
					// 	.e("result").t(transaction.getResultObject()).up()
					// and the content will be data:  "content","data", besides the fact that their will be a section <data>
		}catch(Exception e){
		}
		 
		return xmlstr;
		
	}
	 
	
	
	/**
	 * for registered instances, an interaction starts with requesting an ID 
	 * requests are sent by instances of the role "SOURCE"
	 * @return 
	 */
	public String createRequestForID( long instanceID , String role, String taskUuid ){ 
		String xmlstr="" ;
	
	
		XMLBuilder builder ;
		
		try{
	
			
			builder = getXmlBuilder( "messageboard" ) ;
			
			builder.a( "name", "spela").a("role", role); 
			
			builder.e("request").a("type", "transaction")
			         .e("role").a("value", role).up()
	                 .e("instance").a("id",""+ instanceID ).up()
					 .e("secret").a("value", taskUuid ).up() ; // needs to be reflected by the MessageBoard
			xmlstr = getXmlStr( builder, true ) ;
	
		}catch(Exception e){
		}
		
		
		 
		return xmlstr;
	}


	/**
	 * the MessageBoard creates a primary receipt ID for a given request ;
	 * any further activity uses this primary receipt and is further identified by a secondary ID (also globally unique)
	 * 
	 * creating & returning a receipt also means to create a slot for further interactions 
	 */
	public String createTransactRequestReceipt( XRegistration xreg , long instanceID, long transactionID , String secret){
		/*  variant 1:
			<messageboard name="spela" role="SOURCE">
				<request type="transactionID">
					<role value="SOURCE"/>
					<instance id="234"/>
				</request>
			</messageboard>
	
			variant 2:
			<messageboard name="spela" role="SOURCE">
				<transaction>
	  				<id instance="267" value="2"/>
	  				<name value="test-source-1-85e949cc-de3d-48a7-996a-1475369e30e4"/>
				</transaction>
			</messageboard>
		*/
		 
		
	
		String xmlstr = "", role="", name="" ;
		 
		
		XMLBuilder builder ;
		
		try{
	
			role = xreg.getRole() ;
			name = xreg.getNameOfApplicant() ;
			// port = xreg.getPort() ;
			// id   = xreg.getInstanceID() ;
			
			builder = getXmlBuilder( "messageboard" ) ;
			builder.a( "name", "spela").a("role", role); 
			
			
			builder.e("transaction")
			 		 .e("id").a("value",""+transactionID )
	                   		 .a("instance", ""+instanceID )
	                   		 .a("secret", secret ) 
	                   	.up()
			         .e("name").a("value", name).up();
			
					  
			xmlstr = getXmlStr( builder, true ) ;
	
		}catch(Exception e){
		}
		
		 
		return xmlstr ;
	}



	
	// ------------------------------------------
	// ------------------------------------------

	
	public String removeMessageBoardRoutingMetaTag( String rawXmlMsg){
		
		int p;
		
		p = rawXmlMsg.indexOf("::<?xml");
		if (p>0){
			rawXmlMsg = rawXmlMsg.substring(p, rawXmlMsg.length()) ;
		}
		
		return rawXmlMsg;
	}
	
	/**
	 * 
	 * we retrieve the transaction ID and select the matching object from the opened transactions
	 * 
	 * @param rawXmlMsg
	 * @return
	 */
	public Transaction readTransactionDataDelivery( Transactions transactions, String rawXmlMsg ){
		/*
		<messageboard name="spela" role="SOURCE">
   			<transaction>
   			  	<transactionID value="8"/>
      			<request type="delivery"/>
      			<name value="test-source-1-da033efc-0494-46df-a536-02dc06e74bf5"/>
      			<content type="rawdata,*"/>
      			<data type="9">
			  ... ... 
		*/
		Transaction transaction=null;
		
		String str ;
		int  dt,vi;
		long transactID =-1;

		try {
			
			xpathQuery.setXml(rawXmlMsg);
			str = xpathQuery.getAttributesValue("//messageboard", "messageboard", "role");

			str = xpathQuery.getAttributesValue("//transaction/transactionID", "transactionID", "value");
			
			if ((str.length()>0) && (strgutil.isNumericX(str))){
				transactID = Long.parseLong(str) ;	
			}
			
			if (transactID>0) {
				transaction = transactions.getTransactionByID(transactID) ;

			} // transactID > 0

			if (transaction!=null){
				str = xpathQuery.getAttributesValue("//transaction/content", "content", "type");
				transaction.setContentType(str) ;
				
				str = xpathQuery.getAttributesValue("//transaction/data", "data", "type");
				      dt = getInteger(str,-1);
					  transaction.setType(dt) ;
				
				str = xpathQuery.getAttributesValue("//transaction/linkrelation", "linkrelation", "value");
				      vi = getInteger(str,-1);
				      transaction.setLinkRelation(vi);
				
				str = xpathQuery.getAttributesValue("//transaction/relationitemid", "relationitemid", "value");
					  vi = getInteger(str,-1);
					  transaction.setRelationItemID(vi);
					  
				str = xpathQuery.getAttributesValue("//transaction/relationgroupid", "relationgroupid", "value");
					  vi = getInteger(str,-1);
					  transaction.setRelationGroupID(vi) ;
				// read secret of sending instance
			    str = xpathQuery.getAttributesValue("//transaction/request","request","secret");
			          transaction.setClientSecret(str);
			}
			
		} catch (Exception e) {
		}

		return transaction;
	}
	
	/**
	 * 
	 * returns the object-ed string representing the encoded transaction
	 *  
	 * @param rawXmlMsg
	 * @return
	 */
	public Object readTransactionDataDelivery( String rawXmlMsg ) {
		/*
			... ... 
			<transaction>
		 		<content type="rawdata,*"/>
      			<data type="9">
         			<format zip="0" encoding="base64"/>
         			<values>
						That's a real data table!
         			</values>
      			</data>
		*/
		Object dataobj = null;
		String str ;
		 

		 
		
		try {
			
			xpathQuery.setXml(rawXmlMsg);
			str = xpathQuery.getAttributesValue("//transaction//format", "format", "zip"); // "0" or "1"

			str = xpathQuery.getAttributesValue("//transaction//format", "format", "encoding"); // e.g. "" or "base64"
			
			str = xpathQuery.getElementsIncValue("//transaction/data/values" );
			
			str = strgutil.trimm(str.trim(), "\n");
			if (str!=null) {
				dataobj = new Object();
				dataobj = (Object)str ;
			}

			
		} catch (Exception e) {
		}

		return dataobj;
	}
	
 
	public String removeTag( String rawXmlMsg, String elementLabel){
		
		String resultXml = rawXmlMsg;
		
		if ((elementLabel.trim().length()==0) || ( rawXmlMsg.indexOf(elementLabel)<0)){
			return rawXmlMsg;
		}
		xpathQuery.setXml(rawXmlMsg);
		
		resultXml = xpathQuery.removeElement( elementLabel ) ;
		
		return resultXml;
	}
	
	public String removeDataSection( String rawXmlMsg, String elementLabel){
		
		String resultXml = "";
		
		xpathQuery.setXml(rawXmlMsg);
		
		resultXml = xpathQuery.removeElement( elementLabel ) ;
		
		if (resultXml.length()==0){
			// some kind of accident ? -> revert to original
			resultXml = rawXmlMsg;
		}
		return resultXml;
	}
	
	// ============================================================================================================================
	// ============================================================================================================================



	public void test(){
		/*
		
		<?xml version="1.0" encoding="UTF-8"?>
		
		<Projects>
    		<java-xmlbuilder language="Java" scm="SVN">
        		<Location type="URL">http://code.google.com/p/java-xmlbuilder/</Location>
    		</java-xmlbuilder>
    		<JetS3t language="Java" scm="CVS">
        		<Location type="URL">http://jets3t.s3.amazonaws.com/index.html</Location>
    		</JetS3t>
		</Projects>
		
		*/
		 
		String str;
		Properties outputProperties ;
		XMLBuilder builder ;
		
		
		outputProperties = new Properties();

		// Explicitly identify the output as an XML document
		outputProperties.put(javax.xml.transform.OutputKeys.METHOD, "xml");

		// Pretty-print the XML output (doesn't work in all cases)
		outputProperties.put(javax.xml.transform.OutputKeys.INDENT, "yes");

		// Get 2-space indenting when using the Apache transformer
		outputProperties.put("{http://xml.apache.org/xslt}indent-amount", "2");
		 
		// Omit the XML declaration header <<<<<<<<<<<<<<<<<<<<<
		//creating a xml snippet... as output
		// 
		// outputProperties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes");
		
		
		/*
		
		The following methods are available for adding items to the XML document:

			XML Node 				Methods
			Element					element, elem, e
			Attribute				attribute, attr, a
			Text (Element Value)	text, t
			CDATA					cdata, data, d
			Comment					comment, cmnt, c
			Process Instruction		instruction, inst, i
			Reference				reference, ref, r

		*/
		try {
			builder = XMLBuilder.create("Projects");
			
			builder.e("java-xmlbuilder")
		        .a("language", "Java") // use "attribute" instead of abbr. "a"
		        .a("scm","SVN")                     
		        .e("location")         // use "element" instead of abbr. "e"
		            .a("type", "URL")
		            .t("http://code.google.com/p/java-xmlbuilder/")
		        .up()
		    .up()
		    .e("JetS3t")
		        .a("language", "Java")
		        .a("scm","CVS")
		        .e("location")
		            .a("type", "URL")
		            .a("link","http://jets3t.s3.amazonaws.com/index.html");

		 
			
			// firstLocationBuilder = builder.xpathFind("//location");
			// L2 = builder.xpathFind("//JetS3t").elem("location2").attr("type", "Testing");
			// this is adding a further extension to the XML string
			 
			
			// str = L2.asString(); // L2 contains the whole file ??
			// str = L2.asString(outputProperties) ;
			
			
			// str = firstLocationBuilder.asString(outputProperties);
			
			
			// 
			PrintWriter writer;
			FileOutputStream fos;
			 
			
			fos = new FileOutputStream( "D:/temp/xb_projects.xml" );
			writer = new PrintWriter( fos );

			builder.toWriter(writer, outputProperties);
			
			str = builder.asString(outputProperties);

			
			str = builder.asString(outputProperties);
			str = str.replace("encoding=\"UTF-8\"?>", "encoding=\"UTF-8\"?>\n\n");
			
			writer.close();
			fos.close() ;
			
			fileutil.writeFileSimple( "D:/temp/xb_projects.xml", str) ;
			
			
			// To obtain the Element represented by any given XMLBuilder node: 
			// org.w3c.dom.Element element = xmlBuilderNode.getElement();

			// To obtain the entire XML document:
			org.w3c.dom.Document domDoc = builder.getDocument();
			
			// for FAQ on XPath:  http://www.exampledepot.com/egs/org.w3c.dom/pkg.html
			
			// domDoc
			
			// // get all tags in the document with the name link
			// NodeList links = d.getElementsByTagName( "link" );
			
			
			XPath xpath ;
			XPathExpression expr ;
			Object xresult ;
			NodeList nodes,nodelist ;
			Node node, anode, childnode ;
			NamedNodeMap nodeAttr;
			
			xpath = XPathFactory.newInstance().newXPath();
			expr = xpath.compile("//location");
			
			
			nodelist = domDoc.getElementsByTagName("type");
			
			xresult = expr.evaluate(domDoc, XPathConstants.NODESET);
			nodes = (NodeList) xresult;
			
			for (int i = 0; i < nodes.getLength(); i++) {
				
				node = nodes.item(i);
				str = node.getNodeValue(); // null
				
				str = node.getTextContent(); // http://code.google.com/p/java-xmlbuilder/
				str = node.getNodeName();    // location
				 
				
				nodeAttr = node.getAttributes() ; // attributes are tags !!!
				
				if (nodeAttr!=null){
					for (int ac=0;ac<nodeAttr.getLength();ac++){
						anode = nodeAttr.getNamedItem("URL");  // -> anode=null
						anode = nodeAttr.getNamedItem("type");
						if (anode!=null){
							str = anode.getNodeName() ;   // "type"
							str = anode.getNodeValue() ;  // "URL"
						}
						
						str = nodeAttr.item(ac).getNodeValue() ;
					}
				}
				
				childnode = node.getFirstChild() ;
				if (childnode!=null){
					str = childnode.getLocalName() ;  // null
					str = childnode.getTextContent(); // http://code.google.com/p/java-xmlbuilder/
					str = childnode.getNodeValue();	  //  ./.  ...the same
					
					str = childnode.getNodeName();
					
				}
				// System.out.println( str );
				
			} 
			  
			
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (FactoryConfigurationError e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		} catch (XPathExpressionException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	

}

/*



<xml>
  <messageboard name="spela" role="BOARD" >

	<name value="name_of_source_provider" />
    <port value="" /> 
  
  </messageboard>
============================================================


<xml>
  <messageboard name="spela" role="SOURCE" > 

    <declare sender="">
    </declare>


  </messageboard>



*/





